#ifndef USER_MB_APP_S_H
#define USER_MB_APP_S_H

#include <stdint.h>

#define S_USE_DISCRETE_INPUT   (1)
#define S_USE_COIL             (1)
#define S_USE_REG_INPUT        (1)
#define S_USE_REG_HOLDING      (1)

//离散量输入
#if S_USE_DISCRETE_INPUT == 1
#define S_DISCRETE_INPUT_START 0
#define S_DISCRETE_INPUT_NDISCRETES 64
    #if S_DISCRETE_INPUT_NDISCRETES % 8
        extern uint8_t ucSDiscInBuf[S_DISCRETE_INPUT_NDISCRETES / 8 + 1];
    #else
        extern uint8_t ucSDiscInBuf[S_DISCRETE_INPUT_NDISCRETES / 8];
    #endif
#endif

//线圈
#if S_USE_COIL == 1
#define S_COIL_START 0
#define S_COIL_NCOILS 64
    #if S_COIL_NCOILS % 8
        extern uint8_t ucSCoilBuf[S_COIL_NCOILS / 8 + 1];
    #else
        extern uint8_t ucSCoilBuf[S_COIL_NCOILS / 8];
    #endif
#endif

//输入寄存器
#if S_USE_REG_INPUT == 1
#define S_REG_INPUT_START 0
#define S_REG_INPUT_NREGS 100
extern uint16_t usSRegInBuf[S_REG_INPUT_NREGS];
#endif

//保持寄存器
#if S_USE_REG_HOLDING == 1
#define S_REG_HOLDING_START 0
#define S_REG_HOLDING_NREGS 200
extern uint16_t usSRegHoldBuf[S_REG_HOLDING_NREGS];
#endif

typedef enum
{
    MB_ENOERR,                  /*!< no error. */
    MB_ENOREG,                  /*!< illegal register address. */
    MB_EINVAL,                  /*!< illegal argument. */
    MB_EPORTERR,                /*!< porting layer error. */
    MB_ENORES,                  /*!< insufficient resources. */
    MB_EIO,                     /*!< I/O error. */
    MB_EILLSTATE,               /*!< protocol stack in illegal state. */
    MB_ETIMEDOUT                /*!< timeout error occurred. */
} eMBErrorCode;

typedef enum
{
    MB_REG_READ,                /*!< Read register values and pass to protocol stack. */
    MB_REG_WRITE                /*!< Update register values. */
} eMBRegisterMode;
/**
 * Modbus slave coils callback function.
 *
 * @param pucRegBuffer coils buffer
 * @param usAddress coils address
 * @param usNCoils coils number
 * @param eMode read or write
 *
 * @return result
 */
eMBErrorCode eMBRegCoilsCB(uint8_t * pucRegBuffer, uint16_t usAddress,uint16_t usNCoils, eMBRegisterMode eMode);

/**
 * Modbus slave discrete callback function.
 *
 * @param pucRegBuffer discrete buffer
 * @param usAddress discrete address
 * @param usNDiscrete discrete number
 *
 * @return result
 */
eMBErrorCode eMBRegDiscreteCB( uint8_t * pucRegBuffer, uint16_t usAddress, uint16_t usNDiscrete );

/**
 * Modbus slave input register callback function.
 *
 * @param pucRegBuffer input register buffer
 * @param usAddress input register address
 * @param usNRegs input register number
 *
 * @return result
 */
eMBErrorCode eMBRegInputCB(uint8_t * pucRegBuffer, uint16_t usAddress, uint16_t usNRegs );
/**
 * Modbus slave holding register callback function.
 *
 * @param pucRegBuffer holding register buffer
 * @param usAddress holding register address
 * @param usNRegs holding register number
 * @param eMode read or write
 *
 * @return result
 */
eMBErrorCode eMBRegHoldingCB(uint8_t * pucRegBuffer, uint16_t usAddress,uint16_t usNRegs, eMBRegisterMode eMode);

/**
 * @brief  向保持寄存器buf中写一个寄存器的值
 * @param  RegAddr:寄存器的起始地址,寄存器地址是从0开始
 * @retval 寄存器的值
 */
void MB_S_WriteOneHoldBuf(uint16_t RegAddr,uint16_t value);
/**
 * @brief  从保持寄存器buf中读取一个寄存器的值
 * @param  RegAddr:寄存器的起始地址,寄存器地址是从0开始
 * @retval 寄存器的值
 */
uint16_t MB_S_ReadOneHoldBuf(uint16_t RegAddr);
#endif
